import store from '@/store'
import config from '@/config'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { toast, showConfirm, tansParams } from '@/utils/common'
import guid from '@/uview-ui/libs/function/guid'

let timeout = 15000
const baseUrl = config.baseUrl

const upload = (config, popError=true, onprocess=null) => {
  // 是否需要设置 token
  const isToken = (config.headers || {}).isToken === false
  config.header = config.header || {}
  if (getToken() && !isToken) {
    config.header['Authorization'] = 'Bearer ' + getToken()
  }
  // get请求映射params参数
  if (config.params) {
    let url = config.url + '?' + tansParams(config.params)
    url = url.slice(0, -1)
    config.url = url
  }
  let isFinish = false
  return new Promise((resolve, reject) => {
      let uploadTask = uni.uploadFile({
        timeout: config.timeout || timeout,
        url: baseUrl + config.url,
        filePath: config.filePath,
        name: config.name || 'file',
        header: config.header,
        formData: config.formData,
        success: (res) => {
          let result = JSON.parse(res.data)
          const code = result.code || 200
          const msg = errorCode[code] || result.msg || errorCode['default']
          if (code === 200) {
            resolve(result)
          } else if (code == 401) {
            showConfirm("登录状态已过期，您可以继续留在该页面，或者重新登录?").then(res => {
              if (res.confirm) {
                store.dispatch('LogOut').then(res => {
                  uni.reLaunch({ url: '/pages/login/login' })
                })
              }
            })
            reject('无效的会话，或者会话已过期，请重新登录。')
          } else if (code === 500) {
            toast(msg)
            reject('500')
          } else if (code !== 200) {
            toast(msg)
            reject(code)
          }
        },
        fail: (error) => {
          let message = error["message"] || error["errMsg"]
          if (message == 'Network Error') {
            message = '服务器连接异常'
          } else if (message.includes('timeout')) {
            message = '系统接口请求超时'
          } else if (message.includes('Request failed with status code')) {
            message = '系统接口' + message.substr(message.length - 3) + '异常'
          } else if (message.includes('abort') || message.includes('fail')) {
            // 内部错误类型判断
            message = '信号不佳，请求超时'
          }
          if(message && popError) { toast(message) }
          reject(error)
        },
        complete: () => {
          isFinish = true
        }
      })
      // 监听上传进度
      if (onprocess) {
        uploadTask.onProgressUpdate((res) => {
          onprocess(res)
        })
      }
      setTimeout(()=> {
        if (!isFinish) { uploadTask.abort() }
      }, config.timeout || timeout)

  })
}

export default upload

/**
 * 临时路径转base64
 * @param tempFilePath
 * @return {Promise<unknown>}
 */
export function pathToBase64(tempFilePath) {
  return new Promise((resolve, reject) => {
    plus.io.resolveLocalFileSystemURL(tempFilePath, entry => {
      entry.file(file => {
        const fileReader = new plus.io.FileReader()
        fileReader.readAsDataURL(file)
        fileReader.onloadend = event => {
          const base64 = event.target.result
          resolve(base64)
        }
        fileReader.onerror(err => {reject(err)})
      })
    }, err => {reject(err)})
  })
}

/**
 * base64转临时路径
 * @param base64
 * @returns
 */
export function base64ToPath(base64) {
  return new Promise(function(resolve, reject) {
    if (typeof window === "object" && "document" in window) {
      base64 = base64.split(",");
      var type = base64[0].match(/:(.*?);/)[1];
      var str = atob(base64[1]);
      var n = str.length;
      var array = new Uint8Array(n);
      while (n--) {
        array[n] = str.charCodeAt(n);
      }
      return resolve(
        (window.URL || window.webkitURL).createObjectURL(
          new Blob([array], { type: type })
        )
      );
    }
    var extName = base64.match(/data\:\S+\/(\S+);/);
    if (extName) {
      extName = extName[1];
    } else {
      reject(new Error("base64 error"));
    }
    var fileName = guid() + "." + extName;
    if (typeof plus === "object") {
      var basePath = "_doc";
      var dirPath = "uniapp_temp";
      var filePath = basePath + "/" + dirPath + "/" + fileName;
      if (
        compareVersions(
          plus.os.name === "Android" ? "1.9.9.80627" : "1.9.9.80472",
          plus.runtime.innerVersion
        ) === -1
      ) {
        plus.io.resolveLocalFileSystemURL(
          basePath,
          function(entry) {
            entry.getDirectory(
              dirPath,
              {
                create: true,
                exclusive: false,
              },
              function(entry) {
                entry.getFile(
                  fileName,
                  {
                    create: true,
                    exclusive: false,
                  },
                  function(entry) {
                    entry.createWriter(function(writer) {
                      writer.onwrite = function() {
                        resolve(filePath);
                      };
                      writer.onerror = reject;
                      writer.seek(0);
                      writer.writeAsBinary(
                        base64.replace(
                          /^data:\S+\/\S+;base64,/,
                          ""
                        )
                      );
                    }, reject);
                  },
                  reject
                );
              },
              reject
            );
          },
          reject
        );
        return;
      }
      var bitmap = new plus.nativeObj.Bitmap(fileName);
      bitmap.loadBase64Data(
        base64,
        function() {
          bitmap.save(
            filePath,
            {},
            function() {
              bitmap.clear();
              resolve(filePath);
            },
            function(error) {
              bitmap.clear();
              reject(error);
            }
          );
        },
        function(error) {
          bitmap.clear();
          reject(error);
        }
      );
      return;
    }
    if (typeof wx === "object" && wx.canIUse("getFileSystemManager")) {
      var filePath = wx.env.USER_DATA_PATH + "/" + fileName;
      wx.getFileSystemManager().writeFile({
        filePath: filePath,
        data: base64.replace(/^data:\S+\/\S+;base64,/, ""),
        encoding: "base64",
        success: function() {
          resolve(filePath);
        },
        fail: function(error) {
          reject(error);
        },
      });
      return;
    }
    reject(new Error("not support"));
  });
}

/**
 *
 * @param v1
 * @param v2
 * @return {number}
 * compareVersions('1.11', '1.9'); // 1
 * compareVersions('1.9', '1.11'); // -1
 * compareVersions('1.1', '1.1.0'); // 0
 */
function compareVersions(v1, v2) {
  var v1parts = v1.split('.');
  var v2parts = v2.split('.');

  for (var i = 0; i < v1parts.length; ++i) {
    if (v2parts.length == i) {
      return 1;
    }

    if (v1parts[i] == v2parts[i]) {
      continue;
    }
    else if (v1parts[i] > v2parts[i]) {
      return 1;
    }
    else {
      return -1;
    }
  }

  if (v1parts.length != v2parts.length) {
    return -1;
  }

  return 0;
}
